﻿#include "facade.h"
#include "ui_facade.h"
#include <QDebug>

Facade::Facade(QWidget *parent) :
    TransFacade(parent),
    ui(new Ui::Facade)
{
    ui->setupUi(this);

    skin_note;

    defPos.setY(DEF_HEI);
    this->move(defPos);

    userLand=Location::document + APP_ROOT;
    QDir dir(userLand);
    if(!dir.exists())
        dir.mkpath(userLand);
}

Facade::~Facade()
{
    endReceiver();
    endReminder();
    delete ui;
}

void Facade::connectStorage()
{
    if(QSqlDatabase::contains("qt_sql_default_connection"))
        db=QSqlDatabase::database("qt_sql_default_connection");
    else
    {
        QSettings set(DB_CONFIG,QSettings::IniFormat);
        QString hostName=set.value("Storage/host").toString();
        int port=set.value("Storage/port").toInt();
        QString dbName=set.value("Storage/db").toString();
        QString userName=set.value("Storage/user").toString();
        QString passwd=set.value("Storage/passwd").toString();

        db=QSqlDatabase::addDatabase("QMYSQL");
        db.setHostName(hostName);
        db.setPort(port);
        db.setDatabaseName(dbName);
        db.setUserName(userName);
        db.setPassword(passwd);
    }
}

void Facade::startUp()
{
    note=nullptr;
    note2=nullptr;
    memo=nullptr;
    remindMan=nullptr;
    popup=nullptr;
    searchBox=nullptr;
    connectStorage();

    createMenu();
    startReceiver();
    startReminder();
    checkStaff();

    detectMemo();
}

void Facade::keyPressEvent(QKeyEvent *event)
{
    if(event->modifiers() == Qt::AltModifier && event->key()==Qt::Key_1)
        showNote();
    else if(event->modifiers() == Qt::AltModifier && event->key()==Qt::Key_2)
        showNote2();
    else if(event->modifiers() == Qt::AltModifier && event->key()==Qt::Key_F2)
        showSearchBox();
    else
    {
        switch(event->key())
        {
        case Qt::Key_Home:
            moveDefPos();
            break;
        case Qt::Key_F1:
            QDesktopServices::openUrl(QUrl::fromLocalFile(README));
            break;
        case Qt::Key_F3:
            invokeCalc();
            break;
        }
    }
}

void Facade::mouseDoubleClickEvent(QMouseEvent *)
{
}

QString Facade::getPart() const
{
    QSettings reg(APP_REG,QSettings::NativeFormat);
    return reg.value("part").toString();
}

void Facade::putPart(const QString &part)
{
    QSettings reg(APP_REG,QSettings::NativeFormat);
    reg.setValue("part",part);
}

void Facade::checkStaff()
{
    QSettings reg(APP_REG,QSettings::NativeFormat);
    if(!reg.contains("part"))
    {
        QString part= "sd";
        if(QFile::exists(ETC_STAFF))
        {
            Pivx pivx(QString(ETC_STAFF));
            pivx.setElementTag("host","part");
            if(pivx.load())
            {
                QHash<QString,QVariant> staffTable=pivx.getDetail();
                part=staffTable.contains(Env::hostName)?staffTable.value(Env::hostName).toString():"sd";
            }
        }
        putPart(part);
    }
}

void Facade::startReceiver()
{
    receiver=new Receiver;
    connect(receiver,&Receiver::received,this,&Facade::receivedMessage);
    connect(&recvThread,&QThread::finished,receiver,&QObject::deleteLater);
    receiver->moveToThread(&recvThread);
    recvThread.start();
}

void Facade::startReminder()
{
    if(!db.isOpen())
        if(!db.open())
            return;

    reminder=new Reminder(nullptr,db);
    connect(reminder,&Reminder::raise,this,&Facade::raisedRemind);
    connect(&remindThread,&QThread::finished,reminder,&QObject::deleteLater);
    reminder->moveToThread(&remindThread);
    remindThread.start();
}

void Facade::endReceiver()
{
    recvThread.quit();
    recvThread.wait();
}

void Facade::endReminder()
{
    remindThread.quit();
    remindThread.wait();
}

void Facade::receivedMessage(const QString &label,const QString &detail)
{
    if(label == CMD_HEAD)
    {
        if(detail == CMD_RELOAD_MENU)
            reloadMenu();
    }
    else
        pop(label,detail);
}

void Facade::raisedRemind(const QString &detail)
{
    pop(QStringLiteral("提醒"),detail);
}

void Facade::createMenu()
{
    menu=new QMenu(this);
    generateMenu();
}

void Facade::generateMenu()
{
    if(!db.isOpen())
        if(!db.open())
        {
            menu->addAction(QStringLiteral("退出"),QApplication::quit);
            return;
        }

    if(!menuItems.isEmpty())
        menuItems.clear();

    if(!menuList.isEmpty())
        menuList.clear();

    QSqlQuery query;
    query.exec(QString("select label,detail from %1 where category='%2'").arg(TD_MENU).arg("biz"));
    while(query.next())
    {
        QString label=query.value(0).toString();
        QString detail=query.value(1).toString();
        if(label == "#")
            menu->addSeparator();
        else if(detail == "#menu")
        {
            QMenu *m_menu=menu->addMenu(label);
            menuList.append(m_menu);

            QSqlQuery query;
            query.exec(QString("select label,detail from %1 where category='%2'").arg(TD_MENU).arg(label));
            while(query.next())
            {
                QString label=query.value(0).toString();
                QString detail=query.value(1).toString();
                if(label == "#")
                    m_menu->addSeparator();
                else
                {
                    m_menu->addAction(label);
                    menuItems.insert(label,detail);
                }
            }
        }
        else
        {
            menu->addAction(label);
            menuItems.insert(label,detail);
        }
    }
    menu->addSeparator();
    createPropsMenu();
    menu->addSeparator();
    menu->addAction(QStringLiteral("隐藏"),this,&QWidget::hide);
    createOptionMenu();
    connect(menu,&QMenu::triggered,this,&Facade::processMenuAction);

    db.close();
}

void Facade::reloadMenu()
{
    menu->clear();
    menu->disconnect();

    generateMenu();

    tray->showMessage(QStringLiteral("消息"),
                      QStringLiteral("菜单已刷新"));
}

void Facade::createPropsMenu()
{
    if(!propsMenuItems.isEmpty())
        propsMenuItems.clear();

    QMenu *m_props=menu->addMenu(QStringLiteral("组件"));
    QMenu *m_note=m_props->addMenu(QStringLiteral("速记"));
    m_note->addAction(QStringLiteral("速记1 (Alt+1)"),this,&Facade::showNote);
    m_note->addAction(QStringLiteral("速记2 (Alt+2)"),this,&Facade::showNote2);
    m_props->addAction(QStringLiteral("备忘"),this,&Facade::showMemo);
    m_props->addAction(QStringLiteral("定时提醒"),this,&Facade::showRemind);
    m_props->addAction(QStringLiteral("计算器 (F3)"),this,&Facade::invokeCalc);
    m_props->addSeparator();

    QSqlQuery query;
    query.exec(QString("select label,detail from %1 where category='%2'").arg(TD_MENU).arg("props"));
    while(query.next())
    {
        QString label=query.value(0).toString();
        QString detail=query.value(1).toString();
        propsMenuItems.insert(label,detail);
        m_props->addAction(label);
    }
    connect(m_props,&QMenu::triggered,this,&Facade::processPropsAction);
}

void Facade::createOptionMenu()
{
    QMenu *m_option=menu->addMenu(QStringLiteral("选项"));
    m_option->addSeparator();
    m_option->addAction(QStringLiteral("本机信息"),::sp_aboutDevice);
    m_option->addAction(QStringLiteral("应用信息"),::sp_aboutApp);
    m_option->addAction(QStringLiteral("版本信息"),::sp_aboutVersion);
    m_option->addSeparator();
    m_option->addAction(QStringLiteral("刷新菜单"),this,&Facade::reloadMenu);
    m_option->addSeparator();
    m_option->addAction(QStringLiteral("退出"),QApplication::quit);
}

void Facade::processPropsAction(QAction *action)
{
    QString label=action->text();
    if(!propsMenuItems.contains(label))
        return;

    QString url=propsMenuItems.value(label);
    QProcess::startDetached(Launcher + url);
}

void Facade::processMenuAction(QAction *action)
{
    QString label=action->text();
    if(!menuItems.contains(label))
        return;

    QString url=menuItems.value(label);
    QProcess::startDetached(Launcher + url);
}

void Facade::showNote()
{
    if(note==nullptr)
        note=new Note(this);

    note->setUserLand(userLand);
    note->firstLoad();
    note->move(300,100);
    note->show();
}

void Facade::showNote2()
{
    if(note2==nullptr)
        note2=new Note2(this);

    note2->setUserLand(userLand);
    note2->firstLoad();
    note2->move(400,200);
    note2->show();
}

void Facade::showMemo()
{
    if(memo==nullptr)
        memo=new Memo(this);

    memo->setUserLand(userLand);
    memo->load();
    memo->move(100,100);
    memo->show();
}

void Facade::detectMemo()
{
    if(memo==nullptr)
        memo=new Memo(this);

    memo->setUserLand(userLand);
    memo->move(100,100);
    memo->detect();
}

void Facade::showRemind()
{
    if(!db.isOpen())
        if(!db.open())
            return;

    if(remindMan==nullptr)
    {
        remindMan=new RemindOnce(this,db);
        connect(remindMan,&RemindOnce::timerStart,reminder,&Reminder::generateSchema);
    }

    remindMan->move(100,100);
    remindMan->show();
}

void Facade::invokeCalc()
{
    QDesktopServices::openUrl(QUrl(Calc));
}

void Facade::showSearchBox()
{
    if(searchBox==nullptr)
    {
        searchBox=new SearchBox(this);
        searchBox->move(d_width /2 - 200,50);
    }
    searchBox->show();
}

void Facade::pop(const QString &title, const QString &content)
{
    if(popup == nullptr)
        popup=new Popup(this);
    popup->showMe(title,content);
}
